package com.luo.dt.seata.tcc.service.impl;

import com.luo.dt.common.execption.MsgRuntimeException;
import com.luo.dt.common.model.result.RespResult;
import com.luo.dt.seata.tcc.feign.OrderFeignClient;
import com.luo.dt.seata.tcc.feign.StorageFeignClient;
import com.luo.dt.seata.tcc.model.dto.BusinessDto;
import com.luo.dt.seata.tcc.model.dto.CreateOrderDto;
import com.luo.dt.seata.tcc.model.dto.DeductStorageDto;
import com.luo.dt.seata.tcc.model.entity.Order;
import com.luo.dt.seata.tcc.service.BusinessLocalTccService;
import com.luo.dt.seata.tcc.service.BusinessService;
import io.seata.core.context.RootContext;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * 业务服务 - 实现类
 *
 * @author luo
 * @date 2022-12-03
 */
@Service
@Slf4j
public class BusinessServiceImpl implements BusinessService {

    @Resource
    private StorageFeignClient storageFeignClient;

    @Resource
    private OrderFeignClient orderFeignClient;

    @Resource
    private BusinessLocalTccService businessLocalTccService;


    /**
     * 下单操作 - TCC全局事务通过@GlobalTransctional注解发起
     *
     * @param businessDto 业务参数
     * @return 响应结果
     */
    @Override
    @GlobalTransactional(timeoutMills = 60000 * 2)
    public RespResult<Order> handleBusinessAt(BusinessDto businessDto) {
        log.info("开始TCC全局事务，XID={}", RootContext.getXID());

        /** 调用本地TCC服务（用于实现全局事务中调用本地TCC事务） */
        //this.businessLocalTccService.tryBusiness(businessDto);

        /** 扣减库存 */
        DeductStorageDto deductStorageDto = new DeductStorageDto(businessDto.getCommodityCode(), businessDto.getCount());
        log.info("RPC扣减库存，参数：{}", deductStorageDto);
        RespResult storageResult = this.storageFeignClient.deduct(deductStorageDto);
        log.info("RPC扣减库存，结果：{}", storageResult);
        if (!RespResult.isSuccess(storageResult)) {
            throw new MsgRuntimeException("RPC扣减库存 - 返回失败结果！");
        }

        /** 创建订单 */
        CreateOrderDto createOrderDto = new CreateOrderDto(businessDto.getUserId(), businessDto.getCommodityCode(), businessDto.getCount());
        log.info("RPC创建订单，参数：{}", createOrderDto);
        RespResult<Order> orderResult = this.orderFeignClient.createOrder(createOrderDto);
        log.info("RPC创建订单，结果：{}", orderResult);
        if (!RespResult.isSuccess(orderResult)) {
            throw new MsgRuntimeException("RPC创建订单 - 返回失败结果！");
        }
        return orderResult;
    }

}
